#coding:utf-8
import grequests,requests
import apiBussiness
import re,json

def runApi(apiCase_Id,planId=1):
    """运行测试"""
    content = apiBussiness.case_api_byId(apiCase_Id)
    if content == False:return False

    project_id = content['project_id']
    module_id = content['module_id']

    method = content['method']
    req_type = content['req_type']
    #默认为application/json，其它类型暂不处理
    host = replaceParams(project_id,content['host'])
    path = replaceParams(project_id,content['path'])

    pre_caseId = content['pre_caseId']
    if pre_caseId!="":
        #   查询出caseId，再回调执行一次
        preList = pre_caseId.split(';')
        for pre in preList:
            preObj = apiBussiness.case_api_by_case_Id(project_id,pre_caseId)
            if preObj:
                runApi(preObj.get('id'))
    run_times = content['run_times']
    concurrent = content['concurrent']


    #   查找关联名称，并且替换掉关联的值
    headersJson = replaceParams(project_id,content['headersJson'])
    bodysJson = replaceParams(project_id,content['bodysJson'])
    chkJson = replaceParams(project_id,content['chkJson'])

    #   必须要为json格式，以方便解析相关请求
    headers = apiBussiness.is_json(headersJson)
    if headers == False:return False

    bodysCon = apiBussiness.is_json(bodysJson)
    if bodysCon == False: return False

    chksCon = apiBussiness.is_json(chkJson)
    if chksCon == False: return False
    url = "%s%s"%(host,path)
    #   发送相关请求
    resParamsObj = apiBussiness.case_api_params_srhByCaseId(project_id, content['case_id'])
    list = []
    rsTimeList = []
    resultList = []
    for x in xrange(run_times):
        try:
            responseList = api_grequests(method, url, bodysCon, headers, req_type, concurrent)
            if responseList:
                for response in responseList:
                    #   根据case_id去查询相关的关联内容，并解析出来，更新上去
                    if resParamsObj:
                        for rp in resParamsObj:
                            repalceParamsByResponse(response,rp)
                    #   判断测试结果
                    chkResult = judeResponseResult(response,chksCon,project_id)
                    lenResult = len([x for x in chkResult if x==True])
                    if lenResult== len(chksCon):
                        chkLastResult = True
                    else:
                        chkLastResult = False
                    #   响应时间
                    rspTime = response.elapsed.total_seconds()
                    c = response.request.__dict__
                    del (c['hooks'])
                    del (c['_cookies'])

                    lastResult = {'status_code':response.status_code,'rspTime':rspTime,'chkResult':chkLastResult,'requests':name_value(c),
                                  'responseText':response.text,'responseHeader':name_value(response.headers),'chkResultList':chkResult}
                    # 插入测试结果中
                    apiBussiness.case_api_result(project_id, module_id, planId, chkLastResult, apiCase_Id,
                                                 json.dumps(lastResult),rspTime, path)
                    list.append(lastResult)
                    rsTimeList.append(rspTime)
                    resultList.append(chkLastResult)

            else:
                return "没有执行任务"
        except Exception as e:
            return str(e)
        finally:
            pass

    return list,resultList,rsTimeList

def name_value(obj):
    str = '\r\n'
    for k, v in obj.items():
        try:
            v = json.dumps(v)
        except :
            pass
        finally:
            str = str +"%s:%s"%(k,v)+'\r\n'
    return str
# def name_value(obj):
#     return [{k:v} for k, v in obj.items()]

def judeResponseResult(responseObj,chksCon,project_id):
    """判断测试结果"""
    resultList = []
    for chk in chksCon:
        chkType=chk.get('chkType')
        chkWhere = chk.get('chkWhere')
        chkStr = chk.get('chkStr')
        #   chkStr如果是参数，则先去取此时参数的值
        if len(getParams(chkStr)):
            paramObj = apiBussiness.case_api_params_srhByName(project_id, chkStr)
            if paramObj:
                chkStr = paramObj.get('param_value')
        if chkWhere == 'status_code':
            if chkType == "==":
                if chkStr == "%s"%responseObj.status_code:
                    resultList.append(True)
                else:
                    resultList.append(False)
            elif chkType == "!=":
                if chkStr != "%s"%responseObj.status_code:
                    resultList.append(True)
                else:
                    resultList.append(False)
            if chkType == "in":
                if chkStr in "%s"%responseObj.status_code:
                    resultList.append(True)
                else:
                    resultList.append(False)
            elif chkType == "not in":
                if chkStr not in "%s"%responseObj.status_code:
                    resultList.append(True)
                else:
                    resultList.append(False)
        elif chkWhere == 'responseHeader':
            if chkType == "in":
                if chkStr in "%s"%responseObj.headers:
                    resultList.append(True)
                else:
                    resultList.append(False)
            elif chkType == "not in":
                if chkStr not in "%s"%responseObj.headers:
                    resultList.append(True)
                else:
                    resultList.append(False)
        elif chkWhere == 'responseBody':
            if chkType == "in":
                if chkStr in "%s" % responseObj.text:
                    resultList.append(True)
                else:
                    resultList.append(False)
            elif chkType == "not in":
                if chkStr not in "%s" % responseObj.text:
                    resultList.append(True)
                else:
                    resultList.append(False)
    return resultList


def repalceParamsByResponse(responseObj,resParamsObj):
    """从response对象中解析出关联中的内容"""
    rspHeaders = "%s" % responseObj.headers
    resBodys = responseObj.text

    param_value = "NOT FOUND"
    if resParamsObj.get('param_type') == 2:
        #字符关联
        result = getParams("%s%s"%(rspHeaders,resBodys),leftStr=resParamsObj.get('leftStr'),rightStr=resParamsObj.get('rightStr'))
        if len(result):
            index = 0
            if resParamsObj.get('indexStr')>1:
                index = resParamsObj.get('indexStr') - 1
            param_value = result[index]
    elif resParamsObj.get('param_type') == 3:
        #对象关联，传递的内容为response.headers.name
        #responses = {'data': [{'cc': 'success'}]}
        #hh = "responses.get('data')[0].get('cc')"
        #c = eval(hh)
        #print(c)

        try:
            response = responseObj
            jsonObj = resParamsObj.get('jsonObj')
            param_value = eval(jsonObj)
        except Exception,e:
            param_value = "语法不正确!"
    else:
        return None
    #   将param_value更新到参数中
    apiBussiness.case_api_params_upparam_value(resParamsObj.get('id'),param_value)



def api_grequests(method,url,bodysCon,headers,req_type,concurrent):
    req_list = None

    if method == 'GET':
        req_list =[grequests.request(method, url, params=bodysCon, headers=headers, verify=False) for x in xrange(concurrent) ]
    else:
        if req_type == '0':
            req_list = [grequests.request(method, url, json=bodysCon, headers=headers, verify=False) for x in xrange(concurrent) ]
        elif req_type == '1':
            req_list = [grequests.request(method, url, data=bodysCon, headers=headers, verify=False) for x in xrange(concurrent) ]
    if req_list:
        return grequests.map(req_list)
    return req_list

def replaceParams(project_id, soure):
    result = getParams(soure)
    if len(result):
        newSoure = soure
        for param_name in result:
            param_name = "$%s$"%param_name
            paramObj = apiBussiness.case_api_params_srhByName(project_id,param_name)
            if paramObj:
                param_value = paramObj.get('param_value')
                #   除GET请求外，其它直接取值。因为关联扣作是在执行后response中处理的。此时已已经把值更新上去了
                if paramObj.get('param_type') == 1:
                    #   发送get请求获取相关的值
                    rps_value = ''
                    try:
                        response = requests.get(param_value,verify=False)
                        rps_value = response.text
                    except:
                        rps_value = "Error:发送请求失败"
                    param_value = rps_value
                newSoure = newSoure.replace(param_name,param_value)
        return newSoure
    return soure



def getParams(str,leftStr='\$',rightStr='\$'):
    """匹配$$之间的字符"""
    result = re.findall(r"%s(.+?)%s"%(leftStr,rightStr), str,re.M)
    return result

